package com.epoch.base.annotation;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.epoch.base.constant.Constant;
import com.epoch.base.util.Config;
import com.jfinal.core.Controller;
import com.jfinal.kit.StrKit;
import com.jfinal.plugin.activerecord.ActiveRecordPlugin;
import com.jfinal.plugin.activerecord.Model;

public class AutoBindModels {
	
	private final Logger logger = LoggerFactory.getLogger(AutoBindModels.class);
	
	private String configName = "main";

	private ActiveRecordPlugin arp;
	
	private List<Class<? extends Controller>> excludeClasses = new ArrayList<Class<? extends Controller>>();

	private List<String> includeJars = new ArrayList<String>();

	public AutoBindModels(ActiveRecordPlugin arp) {
		this.arp = arp;
		config();
	}

	public AutoBindModels(String configName, ActiveRecordPlugin arp) {
		this.configName = configName;
		this.arp = arp;
		config();
	}

	public AutoBindModels addJar(String jarName) {
		if (StrKit.notBlank(jarName)) {
			includeJars.add(jarName);
		}
		return this;
	}

	public AutoBindModels addJars(String jarNames) {
		if (StrKit.notBlank(jarNames)) {
			addJars(jarNames.split(","));
		}
		return this;
	}

	public AutoBindModels addJars(String[] jarsName) {
		includeJars.addAll(Arrays.asList(jarsName));
		return this;
	}
	
	public AutoBindModels addJars(List<String> jarsName) {
		includeJars.addAll(jarsName);
		return this;
	}

	public AutoBindModels addExcludeClass(Class<? extends Controller> clazz) {
		if (clazz != null) {
			excludeClasses.add(clazz);
		}
		return this;
	}

	public AutoBindModels addExcludeClasses(Class<? extends Controller>[] clazzes) {
		excludeClasses.addAll(Arrays.asList(clazzes));
		return this;
	}

	public AutoBindModels addExcludeClasses(List<Class<? extends Controller>> clazzes) {
		excludeClasses.addAll(clazzes);
		return this;
	}
	
	private void config() {
		List<Class<? extends Model>> controllerClasses = ClassSearcher.findInClasspathAndJars(Model.class, includeJars);
		ModelBind ModelBind = null;
		for (Class model : controllerClasses) {
			if (excludeClasses.contains(model)) {
				continue;
			}
			ModelBind = (ModelBind) model.getAnnotation(ModelBind.class);
			if (ModelBind == null || StrKit.isBlank(ModelBind.table())) {
				continue;
			}
			
			// all default ,so not null
			if (StrKit.isBlank(ModelBind.configName()) || StrKit.isBlank(configName)) {
				logger.error("routes.add is null");
				continue;
			}

			// join many database support
			if (configName.equals(ModelBind.configName())) {
				arp.addMapping(ModelBind.table(), ModelBind.key(), model);
				logger.debug(ModelBind.configName() //
						+ " --> routes.add(" + model + "," + ModelBind.table() + ", " + ModelBind.key() + ")");
			}

		}
	}
	
	public List<Class<? extends Controller>> getExcludeClasses() {
		return excludeClasses;
	}

	public void setExcludeClasses(List<Class<? extends Controller>> excludeClasses) {
		this.excludeClasses = excludeClasses;
	}

	public List<String> getIncludeJars() {
		return includeJars;
	}

	public void setIncludeJars(List<String> includeJars) {
		this.includeJars = includeJars;
	}
}
